package gang.org.springframework.framework.annotation;

import gang.org.springframework.framework.bean.GangAbstractBeanDefinition;
import gang.org.springframework.framework.bean.GangAnnotatedBeanDefinition;
import gang.org.springframework.framework.bean.GangBeanDefinition;
import gang.org.springframework.framework.bean.GangBeanDefinitionHolder;
import gang.org.springframework.framework.io.GangResourceLoader;
import gang.org.springframework.framework.support.GangAnnotationBeanNameGenerator;
import gang.org.springframework.framework.support.GangBeanDefinitionReaderUtils;
import gang.org.springframework.framework.support.GangBeanDefinitionRegistry;
import gang.org.springframework.framework.support.GangBeanNameGenerator;

import java.util.LinkedHashSet;
import java.util.Set;

/**
 * @author gang.chen
 * @Date 2022/9/21 13:03
 */
public class GangClassPathBeanDefinitionScanner extends GangClassPathScanningCandidateComponentProvider{

    private final GangBeanDefinitionRegistry registry;

    private GangBeanNameGenerator beanNameGenerator = GangAnnotationBeanNameGenerator.INSTANCE;

    private GangScopeMetadataResolver scopeMetadataResolver = new GangAnnotationScopeMetadataResolver();

    public GangClassPathBeanDefinitionScanner(GangBeanDefinitionRegistry registry, boolean useDefaultFilters, Object enviroment, GangResourceLoader resourceLoader) {
        this.registry = registry;
        setResourceLoader(resourceLoader);
    }


    public void setBeanNameGenerator(GangBeanNameGenerator beanNameGenerator){
        this.beanNameGenerator = beanNameGenerator != null ? beanNameGenerator : GangAnnotationBeanNameGenerator.INSTANCE;
    }

    public Set<GangBeanDefinitionHolder> doScan(String... basePackages){

        Set<GangBeanDefinitionHolder> beanDefinitionHolders = new LinkedHashSet<>();

        for (String basePackage : basePackages) {

            Set<GangBeanDefinition> candidates = findCandidateComponents(basePackage);

            for (GangBeanDefinition candidate : candidates) {

                GangScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);

                candidate.setScope(scopeMetadata.getScopeName());

                String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);

                if (candidate instanceof GangAbstractBeanDefinition) {
                    //TODO
                }

                if (candidate instanceof GangAnnotatedBeanDefinition) {
                    //TODO
                }

                if (checkCandidate(beanName, candidate)) {

                    GangBeanDefinitionHolder beanDefinitionHolder = new GangBeanDefinitionHolder(candidate, beanName);

                    beanDefinitionHolder = GangAnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, beanDefinitionHolder, this.registry);

                    beanDefinitionHolders.add(beanDefinitionHolder);

                    registerBeanDefinition(beanDefinitionHolder, this.registry);
                }

            }



        }

        return beanDefinitionHolders;
    }

    protected boolean checkCandidate(String name, GangBeanDefinition beanDefinition)
    {
        return true;
    }

    protected void registerBeanDefinition(GangBeanDefinitionHolder definitionHolder, GangBeanDefinitionRegistry registry)
    {
        GangBeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
    }
}
